Flux CD用の AWS CloudFormation コントローラーがリリース(プレビュー)されました

Flux CD用の AWS CloudFormation コントローラーがリリース(プレビュー)されました

Clock Icon2023.05.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「Flux でCloudFormationをデプロイ! CloudFormationでもPull型のGitOpsが始まる!?」

Fluxを使用して、CloudFormationをデプロイできるようになりました。

以下のアップデートの紹介ブログです。

Introducing the AWS CloudFormation Template Sync Controller for Flux

Fluxとは

Gitリポジトリで宣言された状態とKubernetesクラスタの状態を同期するツールです。

類似のツールとしては、Argo CDなどがあげられます。

CDに使われるツールでGitリポジトリ上のコードが変更されたら、自動的にクラスターにデプロイすることができます。

「GitHub ActionsやAWSのCodeシリーズなどのCI/CDツールと何が違うの?」と思う方もいるかもしれません。

FluxやArgo CDなどはGitOpsツール(Pull型)と言われます。(Github Actions等はCIOps(Push型))

リポジトリへのPushをトリガーにするわけではなく、FluxがKubernetesクラスター上でGitリポジトリの変更をポーリング(Pull)して変更があったら反映(デプロイ)するためです。

Flux

CIOpsとGitOpsについては、以下の記事の説明が分かりやすいです。

CIOpsとGitOpsの話 - inductor's blog

何が嬉しい?

CloudFormationをFluxで管理できることで、以下のようなメリットがあります。

  • 正しい設定にリソースを保ちやすい
  • KubernetesとCloudFormationのCDを1つのツールで行える
  • CD用の権限をAWS外部に渡す必要がない

正しい設定にリソースを保ちやすい

Push型のCIOpsでは、CloudFormationが実行されるのはトリガー時(特定ブランチへのPush等)だけです。

もし手動でAWSリソースが変更された場合、次のPushまではAWSリソースとコードの状態が一致しません。

しかし、Pull型のGitOpsは定期的にGitリポジトリをPollingします。

Gitリポジトリの状態を正として、リソースに差分があればGitリポジトリで定義されている状態に変更します。

リソースを正しい設定状態に保ちやすいのがメリットだと思います。  

KubernetesとCloudFormationのCDを1つのツールで行える

既にFluxを使用していてかつ、CloudFormationも使っている場合、CloudFormation用にCDの仕組みを作らなくても、FluxにCDを統一できるメリットもあります。

CD用の権限をAWS外部に渡す必要がない

Pull型のGitOpsのメリットとして、認証情報を外部に渡す必要がないというのも挙げられます。

Github ActionsやCircle CI等でCloudFormationのデプロイを行う場合は、AWS外部に認証情報を渡す必要がありました。

EKSに権限を渡せばいいので、AWS外部に認証情報を渡す必要がありません。 (Codeシリーズだったら、AWS外部に渡さないでCloudFormationデプロイは可能ですが。)

やってみる

前提条件

以下をローカルPC上で使用できるようにしておく必要があります。

構成図

FluxのCloudFormation Controllerを使用して、CloudFormation Stackを作成してみます。

CloudFormationでは、Parameter Storeを作成します。

フォルダ構成

最終的なフォルダ構成を紹介します。

CodeCommitを2つ使用します。(手順中のサンプルリソース作成用CloudFormationでデプロイします)

リポジトリ名 概要
my-flux-configuration Fluxマニフェストファイル保存用
my-cloudformation-templates CloudFormationテンプレートファイル保存用
# my-flux-configuration リポジトリ
$ tree my-flux-configuration/
my-flux-configuration
├── cfn-controller-source.yaml # cfn controllerのGitリポジトリ設定
├── cfn-controller.yaml # cfn controllerデプロイ
├── cfn-stack.yaml # cfn stackデプロイ
├── cfn-templates-repo.yaml # my-cloudformation-templatesのGitリポジトリ設定
└── flux-system
    ├── gotk-components.yaml
    ├── gotk-sync.yaml
    └── kustomization.yaml
# my-cloudformation-templates リポジトリ
$ tree my-cloudformation-templates/
my-cloudformation-templates
└── template.yaml # デプロイするCloudFormationテンプレート

eksctlでクラスター作成

$ eksctl create cluster \
--name flux-cfn-sample \
--region ap-northeast-1 \
--node-type t3.small \
--nodes 2

FluxのCloudFormationコントローラーがリソースを操作できるように権限を付与します。

本来なら必要な権限に絞るべきですが、検証のためPowerUserAccessを与えます。

$ eksctl utils associate-iam-oidc-provider --cluster flux-cfn-sample --approve
$ eksctl create iamserviceaccount \
    --cluster flux-cfn-sample \
    --namespace flux-system \
    --name cfn-controller \
    --role-only \
    --role-name "AWSCloudFormationControllerFluxIRSARole" \
    --attach-policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
    --approve

Fluxの設定ファイル保存用のCodeCommit等の準備

Fluxの設定ファイルやCloudFormationテンプレート等を置くCodeCommitやS3バケットを用意します。

サンプルのCloudFormationを使用して、必要なリソースを作成します。

Fluxのインストール

作成したクラスターでFluxを実行可能か確認します。

問題なければ以下のような出力があります。

$ flux check --pre

► checking prerequisites
✔ Kubernetes 1.25.3 >=1.20.6-0
✔ prerequisites checks passed

リポジトリはサンプルCloudFormationで作成されるCodeCommitを使用します。

flux-gitというIAMユーザーが作成されているため、CodeCommit認証情報を生成してflux bootstrapを行います。

flux bootstrap git \
  --url=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-flux-configuration \
  --branch=main \
  --username=<my-username> \
  --password=<my-password> \
  --token-auth=true

bootstrapを実施したことで、EKSにはFluxのインストールおよび、CodeCommitにFluxを使用するために必要なファイルがpushされました。

CloudFormationコントローラリポジトリをFluxに登録する

CloudFormationコントローラーをFluxで使用できるようにするために、リポジトリをFluxに登録します。

任意のディレクトリにFluxのCodeCommitリポジトリをCloneします。

git clone codecommit::ap-northeast-1://my-flux-configuration

以下のファイルを作成して、CodeCommitにPushします。

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: aws-cloudformation-controller-for-flux
  namespace: flux-system
spec:
  interval: 1h
  timeout: 60s
  ref:
    branch: main
  url: https://github.com/awslabs/aws-cloudformation-controller-for-flux
git add .
git commit -m "add: cfn controller repo"
git push origin HEAD

Pushまでできたら、以下のコマンドを実行してFluxがリポジトリに正常に接続できることを確認します。

$ flux reconcile source git flux-system
$ flux reconcile source git aws-cloudformation-controller-for-flux

Fluxを使用してCloudFormationコントローラーをデプロイする

CloudFormationコントローラーをデプロイします。

以下のファイルを用意して、CodeCommitにPushします。

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: aws-cloudformation-controller-for-flux
  namespace: flux-system
spec:
  interval: 5m
  path: ./config/default
  prune: true
  wait: true
  timeout: 5m
  sourceRef:
    kind: GitRepository
    name: aws-cloudformation-controller-for-flux
  patches:
    - patch: |
        apiVersion: v1
        kind: ServiceAccount
        metadata:
          name: cfn-controller
          annotations:
            eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/AWSCloudFormationControllerFluxIRSARole # AWSアカウントIDを書き換える
      target:
        kind: ServiceAccount
        name: cfn-controller
    - patch: |
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: cfn-controller
        spec:
          template:
            spec:
              containers:
              - name: manager
                env:
                  - name: AWS_REGION
                    value: "ap-northeast-1"
                  - name: TEMPLATE_BUCKET
                    value: "<バケット名>" # サンプルCFnで作成したバケット名
      target:
        kind: Deployment
        name: cfn-controller
git add .
git commit -m "add: cfn controller"
git push origin HEAD

以下のコマンドでデプロイを確認します。

$ flux reconcile source git flux-system
$ flux reconcile kustomization aws-cloudformation-controller-for-flux
$ kubectl rollout status deployment/cfn-controller -n flux-system
$ kubectl logs deployment/cfn-controller -n flux-system

CloudFormationコントローラーのFlux通知の有効化

CloudFormationコントローラーはサードパーティーコントローラーのため、以下の設定を追加して通知を有効化します。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - gotk-components.yaml
  - gotk-sync.yaml
patches:
  - patch: |
      - op: add
        path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/eventSources/items/properties/kind/enum/-
        value: CloudFormationStack
      - op: add
        path: /spec/versions/1/schema/openAPIV3Schema/properties/spec/properties/eventSources/items/properties/kind/enum/-
        value: CloudFormationStack
    target:
      kind: CustomResourceDefinition
      name:  alerts.notification.toolkit.fluxcd.io
  - patch: |
      - op: add
        path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/resources/items/properties/kind/enum/-
        value: CloudFormationStack
      - op: add
        path: /spec/versions/1/schema/openAPIV3Schema/properties/spec/properties/resources/items/properties/kind/enum/-
        value: CloudFormationStack
    target:
      kind: CustomResourceDefinition
      name:  receivers.notification.toolkit.fluxcd.io
  - patch: |
      - op: add
        path: /rules/-
        value:
          apiGroups: [ 'cloudformation.contrib.fluxcd.io' ]
          resources: [ '*' ]
          verbs: [ '*' ]
    target:
      kind: ClusterRole
      name:  crd-controller-flux-system

CloudFormationテンプレートリポジトリにテンプレートファイルをPush

CloudFormationテンプレートファイル用のリポジトリにテンプレートファイルをPushします。

このテンプレートファイルがFluxによって、デプロイされます。

$ git clone codecommit::ap-northeast-1://my-cloudformation-templates
$ cd my-cloudformation-templates
$ touch template.yaml
Resources:
  SampleResource:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Value: "Hello World"
$ git add .
$ git commit -m "add: temaplte file"
$ git push origin HEAD

CloudFormation用のCodeCommitリポジトリと接続

FluxがCloudFormation用のCodeCommitリポジトリの内容を見れるように設定を行います。

bootstrap時に使用したCodeCommitの認証情報をSecretに登録します。

$ CODECOMMIT_USERNAME="<CodeCommitユーザー名>"
$ CODECOMMIT_PASSWORD="<CodeCommitパスワード>"
$ flux create secret git cfn-template-repo-auth \
    --url=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-cloudformation-templates \
    --username=$CODECOMMIT_USERNAME \
    --password=$CODECOMMIT_PASSWORD

fluxの設定リポジトリに移動して、以下のファイルを作成します。

$ cd my-flux-configuration
$ touch cfn-templates-repo.yaml cfn-stack.yaml

cfn-templates-repo.yamlはCloudFormation用のCodeCommitリポジトリを登録します。

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: my-cfn-templates-repo
  namespace: flux-system
spec:
  url: https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-cloudformation-templates
  interval: 5m
  ref:
    branch: main
  secretRef:
    name: cfn-template-repo-auth

cfn-stack.yamlでは、デプロイするCloudFormation Stackの設定を行います。

このファイルで、同期の間隔やStack名などを定義します。

apiVersion: cloudformation.contrib.fluxcd.io/v1alpha1
kind: CloudFormationStack
metadata:
  name: my-cfn-stack
  namespace: flux-system
spec:
  stackName: my-cfn-stack-deployed-by-flux
  templatePath: ./template.yaml
  sourceRef:
    kind: GitRepository
    name: my-cfn-templates-repo
  interval: 1h
  retryInterval: 5m
  destroyStackOnDeletion: true

ファイルの用意ができたら、リポジトリにPushします。

$ git add .
$ git commit -m "add: cfn stack file"
$ git push origin HEAD

動作確認: CloudFormation Stackデプロイ確認

先ほどのファイルのPushができたら、自動的にCloudFormation Stackが作成されます。

まずは、kubectlコマンドで確認してみます。

デプロイが成功していれば、以下のような出力を確認できます。

$ kubectl describe cfnstack my-cfn-stack --namespace flux-system
Name:         my-cfn-stack
Namespace:    flux-system
Labels:       kustomize.toolkit.fluxcd.io/name=flux-system
              kustomize.toolkit.fluxcd.io/namespace=flux-system
Annotations:  <none>
API Version:  cloudformation.contrib.fluxcd.io/v1alpha1
Kind:         CloudFormationStack
Metadata:
  Creation Timestamp:  2023-05-10T08:43:54Z
  Finalizers:
    finalizers.cloudformation.contrib.fluxcd.io
  Generation:  1
  Managed Fields:
    API Version:  cloudformation.contrib.fluxcd.io/v1alpha1
    Fields Type:  FieldsV1
# 省略

マネジメントコンソールからも確認してみましょう。

Flux CDで定義したスタックmy-cfn-stack-deployed-by-fluxが確認できます。

CloudFormationを変更して、CodeCommitにPushで自動的にデプロイされるか確認します。

Parameter StoreのValueをHello WorldからHello Flux CloudFormation Controllerに変更しました。

commitして、CodeCommitにPushしました。

$ git diff
diff --git a/template.yaml b/template.yaml
index 51b5e79..752a177 100644
--- a/template.yaml
+++ b/template.yaml
@@ -3,4 +3,4 @@ Resources:
     Type: AWS::SSM::Parameter
     Properties:
       Type: String
-      Value: "Hello World"
+      Value: "Hello Flux Cloudformation Controller"

少し待つと変更した値にパラメータストアの値が変わっていることを確認できました。

クリーンアップ

EKSクラスターを削除します。

$ eksctl delete cluster --name=flux-cfn-sample

まとめ

Terraform用のControllerはあったみたいですが、CloudFormationもきましたね。

How to GitOps Your Terraform | Flux

EKSの運用が必要になるので少し敷居は高いと思いますが、CloudFormationでもGitOpsが可能になるのは激アツだと思いました。

以上、AWS事業本部の佐藤(@chari7311)でした。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.